// MultiPlayerTag_Client
//
//

//  created by PA, April 16, 2013 (derived from Processing SharedCanvasServer/Client example)
//                                    Shared Drawing Canvas (Server) by Alexander R. Galloway. 
//                                    A server that shares a drawing canvas between two computers. 
// modified by PA, April 26, 2013 (server parse and draw of muliple client messages)
// modified by PA,   May 21, 2013 (more general messaging format)

// Plan:
//
//   x - Client gets a user name from human
//  x  - Client sends Fetch to server
//        FETCH 00000 99999 UserName
//   x - Server looks at list of client objects
//   x     If new client
//   x         add to list
//            assign incremented ID
//   x     else
//    x        can't use that name, inform client
//
//  x  - Send new ID to the client that made request

//     - Client needs to recognize and process new info in JOIN

import processing.net.*;
//import processing

Client aclient;

String input;

float data[];
boolean bIsIt = true;

float xo = 10;
float yo = 10;

String type;
String strMyName = "Mark" + str(round(random(1000)));

CPlayer playerMe = null;

ArrayList listPlayers = new ArrayList();


void setup() 
{
    size(450, 255);
    background(204);
    stroke(0);
    frameRate(10); // Slow it down a little
    // write/readString fails at 30

        // Connect to the server's IP address and port
    aclient = new Client( this, "127.0.0.1", 12345 ); // Replace with your server's IP and port

    // Send my ID and initial position to the server.
    //  aclient.write( str( playerMe.nID  ) + " " + str( playerMe.pos.x ) + " " + str( playerMe.pos.y ) + "\n" );
    //    type = "POS";
    //    aclient.write(       type +
    //             " " + str( playerMe.nID  ) +
    //             " " + str( 00001  ) +
    //             " " + str( playerMe.pos.x  ) + 
    //             "," + str( playerMe.pos.y  ) + "\n" );

    sendFETCH ( strMyName );
    delay(500);
}

void draw() 
{

    background(255);

    // Check for and process any message.
    if ( aclient.available() > 0 ) {

        input = aclient.readString();

        if ( input.indexOf("\n") != -1 ) {

            process_message( input );
        }
        else {
            println( "bad message, no newline:  " + input );
        }
    }

    for ( int i = 0; i < listPlayers.size(); i++ ) {
   
        CPlayer thisPlayer = ( (CPlayer) listPlayers.get(i) );
        
        thisPlayer.draw();
    }
}

void process_message( String input ) {

    print( input + "is message client heard\n" );
    println( "\n" );

    // Sanity check:
    // All messages must contain a newline character '\n'.
    if ( input.indexOf("\n") == -1 ) {

        println( "bad client message, no newline:  " + input );
        return;
    }
    
    
    input = input.substring( 0, input.indexOf("\n") ); // Only up to the newline

    // Parse message header (space separated) and message body (comma separated).
    // See Jacobs language specification on teletag wiki (Google Code) for details.
    String[] strMsgHeader = split( input, ' ' ); 
 
 
     // Check that first part of message is one of our function words; POS, FETCH, JOIN, etc.
    if (   !strMsgHeader[0].equals( "POS" ) 
        && !strMsgHeader[0].equals( "FETCH" )
        && !strMsgHeader[0].equals( "JOIN" ) ) {
            return;
    }
 
    String[] strMsgBody;
    if ( match( input, "," ) == null ) {
        
        // Either bad message 
        //OR
        // The last part is the full body of the message.
        strMsgBody = new String[1];
        strMsgBody[0] = strMsgHeader[3];
    }
    else{
        strMsgBody = split( strMsgHeader[3], ',' );
    } 
 
    // Sanity check:
    // All messages must start with a valid command: 'POS', 'FETCH', 'JOIN'
    int iCommand = -1;
    if ( strMsgHeader[0].equals( "POS"    ) ){ iCommand = 1; }
    if ( strMsgHeader[0].equals( "FETCH"  ) ){ iCommand = 2; }
    if ( strMsgHeader[0].equals( "JOIN" ) ){ iCommand = 3; }
    
    switch ( iCommand ) {
        
        case 1:
        case 2:
        case 3:
            break;
            
        default:
            println( "bad client message, no newline:  " + input );
            return;
    }       
        
println( strMsgHeader );
println( strMsgBody + "\n" );

    int nIDsender = int( strMsgHeader[1] );

    // Process an assign command
    if ( strMsgHeader[0].equals( "JOIN" ) ) {

        receiveJOIN( int( strMsgBody[1] ), strMsgBody[0] ); // new assigned ID
    }

    // Process position command.
    if ( strMsgHeader[0].equals( "POS" ) ) {
       
        // If not my own ID:
        if ( nIDsender != playerMe.nID ) {
            
            // If this player is not on list, add to list:
            CPlayer thisPlayer = getPlayerFromID( listPlayers, nIDsender );    
            if ( thisPlayer == null ) {
                listPlayers.add( new CPlayer( false, nIDsender, "unknown" ) );
                thisPlayer = getPlayerFromID( listPlayers, nIDsender );
            }
            
            thisPlayer.pos.x = float( strMsgBody[0] );
            thisPlayer.pos.y = float( strMsgBody[1] );
      
            thisPlayer.draw();
        }
        
        
//        // which player in list has this ID
//        CPlayer thisPlayer = getPlayerFromID( listPlayers, nIDsender );
// // int a = (val) ? this : that
// 
//        if ( thisPlayer != null ) {
//            
//            thisPlayer.pos.x = float( strMsgBody[0] );
//            thisPlayer.pos.y = float( strMsgBody[1] );
//                    
//            thisPlayer.draw();
//        }

     }
}

CPlayer getPlayerFromID( ArrayList listOfPlayers, int IDtoFind ) {
    
    for ( int i = 0; i < listOfPlayers.size(); i++ ) {
   
        CPlayer thisPlayer = ( (CPlayer) listOfPlayers.get(i) );
        
        if ( thisPlayer.nID == IDtoFind ) {
            
            return thisPlayer;
        }
    }
    
    return null;
}

void sendPOS (float x, float y) {
    
    type = "POS";
    aclient.write(       type +
        " " + str( playerMe.nID  ) +
        " " + str( 00001 ) +
        " " + str( x  ) + 
        "," + str( y  ) + "\n" );
}
void sendFETCH (String strName) {

    // request a unique ID
    type = "FETCH";
    aclient.write(       type +
        " " + str( 00000  ) +
        " " + str( 99999  ) +
        " " + strName + "\n" );
}

void receiveJOIN( int ID, String strNewName ) {

    // My newly assigned unique ID:
    if ( playerMe == null ) {
        
        playerMe = new CPlayer( false, ID, strNewName );
        listPlayers.add( playerMe );
    }

    println(ID);
    println(strNewName);
}

void keyPressed() {

    if ( key == CODED && playerMe != null ) {

        switch ( keyCode ) {

        case    UP: 
            playerMe.pos.y -= 5; 
            break;
        case  DOWN: 
            playerMe.pos.y += 5; 
            break;
        case  LEFT: 
            playerMe.pos.x -= 5; 
            break;
        case RIGHT: 
            playerMe.pos.x += 5; 
            break;
        }

        // Send my ID and initial position to the server.
        sendPOS( playerMe.pos.x , playerMe.pos.y );
    }
}

